package service

import (
	"PolarDay/common/logger"
	"PolarDay/common/requet"
	"PolarDay/common/response"
	"PolarDay/common/returnCode/bCode"
	"PolarDay/common/returnCode/eCode"
	"PolarDay/common/utils"
	"PolarDay/models/entitys"
	"PolarDay/repository"

	"github.com/gin-gonic/gin"
)

type ISysApiService interface {
	GetApi(c *gin.Context, id int)
	SaveApi(c *gin.Context, sysApi *entitys.SysApi)
	UpdateApi(c *gin.Context, sysApi *entitys.SysApi)
	DeleteApi(c *gin.Context, id int)
	ListApi(c *gin.Context, reqCond *requet.RequetPaging)
	GetApiTrees(c *gin.Context)
	GetApiTreeById(c *gin.Context, id int)
	GetApiTree(id int) *entitys.SysApiTree
	CutApiTree(flag bool, trees []entitys.SysApiTree, menuApiIds []int32) []entitys.SysApiTree
}

type SysApiService struct {
	Repo repository.ISysApiRepo `inject:""`
	Log  logger.ILogger         `inject:""`
}

// 获取API
func (apiService *SysApiService) GetApi(c *gin.Context, id int) {
	apiService.Log.Infof("Get api: id = %s", id)
	data := apiService.Repo.GetApiById(id)
	if data == nil {
		response.RespB406s(c, bCode.Api, eCode.P0301, "", nil)
	} else {
		response.RespB200(c, bCode.Api, data)
	}
}

// 保存API
func (apiService *SysApiService) SaveApi(c *gin.Context, sysApi *entitys.SysApi) {
	apiService.Log.Info("Save api: api = %s", sysApi)
	if apiService.Repo.InsertApi(sysApi) {
		response.RespB200(c, bCode.Api, sysApi)
	} else {
		response.RespB406(c, bCode.Api, eCode.P0313, nil)
	}
}

// 更新API
func (apiService *SysApiService) UpdateApi(c *gin.Context, sysApi *entitys.SysApi) {
	apiService.Log.Info("Update api: api = %s", sysApi)
	if apiService.Repo.UpdateApi(sysApi) {
		response.RespB200(c, bCode.Api, sysApi)
	} else {
		response.RespB406(c, bCode.Api, eCode.P0312, nil)
	}
}

// 删除Api
func (apiService *SysApiService) DeleteApi(c *gin.Context, id int) {
	apiService.Log.Info("Delete api: id = %s", id)
	if apiService.Repo.DeleteApi(id) {
		response.RespB200(c, bCode.Api, "")
	} else {
		response.RespB406s(c, bCode.Api, eCode.P0302, "", nil)
	}
}

// 获取Api列表
func (apiService *SysApiService) ListApi(c *gin.Context, reqCond *requet.RequetPaging) {
	apiService.Log.Info("List api, condition = %s", reqCond)
	page := reqCond.Page
	size := reqCond.Size
	var total int32
	where := utils.GetFilter(reqCond.Filter)
	apis := apiService.Repo.ListApi(page, size, &total, where)
	res := make(map[string]interface{})
	res["records"] = apis
	res["total"] = total
	response.RespB200(c, bCode.Api, res)
}

// 完整API树
func (apiService *SysApiService) GetApiTrees(c *gin.Context) {
	apiService.Log.Info("Get api tree")
	apiTree := apiService.GetApiTree(1)
	if apiTree == nil {
		response.RespB406(c, bCode.Api, eCode.P0301, nil)
	} else {
		res := []entitys.SysApiTree{*apiTree}
		response.RespB200(c, bCode.Api, res)
	}
}

// 指定ID的API树
func (apiService *SysApiService) GetApiTreeById(c *gin.Context, id int) {
	apiService.Log.Info("Get api tree by id, id = %s", id)
	// todo 检查ID
	apiTree := apiService.GetApiTree(id)
	if apiTree == nil {
		response.RespB406(c, bCode.Api, eCode.P0301, nil)
	} else {
		response.RespB200(c, bCode.Api, apiTree)
	}
}

func (apiService *SysApiService) GetApiTree(id int) *entitys.SysApiTree {
	var apiTree = entitys.SysApiTree{}
	api := apiService.Repo.GetApiById(id)
	if api == nil {
		return nil
	}
	apiTree.SysApi = *api
	sysApis := apiService.Repo.GetApiByPid(id)
	// 递归查询子节点
	if sysApis == nil {
		apiTree.Children = []entitys.SysApiTree{}
	} else {
		for child := range sysApis {
			apiTree.Children = append(apiTree.Children, *apiService.GetApiTree(int(sysApis[child].Id)))
		}
	}
	return &apiTree
}

// 裁剪
func (apiService *SysApiService) CutApiTree(flag bool, trees []entitys.SysApiTree, menuApiIds []int32) []entitys.SysApiTree {
	for e := range trees {
		if trees[e].Children != nil {
			trees[e].Children = apiService.CutApiTree(flag, trees[e].Children, menuApiIds)
		}
	}
	if flag {
		for i := 0; i < len(trees); {
			if (trees[i].Children == nil || len(trees[i].Children) == 0) && !contains(menuApiIds, trees[i].Id) {
				if i == len(trees)-1 {
					trees = trees[:i]
				} else {
					trees = append(trees[:i], trees[i+1])
				}
			} else {
				i++
			}
		}
	} else {
		for i := 0; i < len(trees); {
			if (trees[i].Children == nil || len(trees[i].Children) == 0) && contains(menuApiIds, trees[i].Id) {
				if i == len(trees)-1 {
					trees = trees[:i]
				} else {
					trees = append(trees[:i], trees[i+1])
				}
			} else {
				i++
			}
		}
	}
	return trees
}
